import abc
from typing import Generic, Optional, TypeVar

AnyKey = TypeVar("AnyKey")
AnyValue = TypeVar("AnyValue")
AnyQuery = TypeVar("AnyQuery")


class Registry(Generic[AnyQuery, AnyValue], abc.ABC):
    @abc.abstractmethod
    def match(self, query: AnyQuery) -> tuple[AnyValue, ...]:
        pass

    def match_one_or_raise(self, query: AnyQuery) -> AnyValue:
        matched = self.match(query)
        if not matched:
            raise KeyError(f"Failed to match query={query}")
        return matched[0]

    def match_one_or_none(self, query: AnyQuery) -> Optional[AnyValue]:
        matched = self.match(query)
        if not matched:
            return None
        return matched[0]


class MutableRegistry(Registry[AnyQuery, AnyValue], Generic[AnyQuery, AnyKey, AnyValue], abc.ABC):
    @abc.abstractmethod
    def register(self, key: AnyKey, value: AnyValue):
        pass
